<template>
	<view class="container">
		<canvas type="webgl" class="webgl" id="gl" canvas-id="gl" @touchstart="handleTouch" @touchmove="handleTouch"
			@touchend="handleTouch"></canvas>
	</view>
</template>

<script>
	import * as THREE from 'three-platformize'
	import {
		OrbitControls
	} from 'three-platformize/examples/jsm/controls/OrbitControls'
	import {
		WechatPlatform
	} from 'three-platformize/src/WechatPlatform'
	import {
		GLTFLoader
	} from 'three-platformize/examples/jsm/loaders/GLTFLoader'
	import {
		DRACOLoader
	} from 'three-platformize/examples/jsm/loaders/DRACOLoader'
	import {
		TextureLoader
	} from 'three-platformize'
	export default {
		data() {
			return {
				disposing: false,
				frameId: null,
				isModelLoaded: false,

				// 添加Promise相关变量
				modelLoadPromise: null,
				resolveModelLoad: null,
				pendingOperations: [],
			};
		},
		created() {
			this.scene = null;
			this.camera = null;
			this.renderer = null;
			this.hanfuModel = null;
			this.controls = null;
			this.light = null;
			this.platform = null;
			this.patternTexture = null;
			this.designTexture = null;

			// 初始化Promise
			this.modelLoadPromise = new Promise((resolve) => {
				this.resolveModelLoad = resolve;
			});
			this.pendingOperations = [];
		},
		onReady() {
			uni.createSelectorQuery().in(this).select('#gl').node().exec((res) => {
				if (!res || !res[0]) {
					console.error('未找到 canvas 元素，请检查 id');
					return;
				}
				const canvas = res[0].node;
				if (!canvas) {
					console.error('canvas 元素为空');
					return;
				}
				// 初始化平台
				this.platform = new WechatPlatform(canvas, {
					enablePhysicalMaterial: true,
				});
				THREE.PLATFORM.set(this.platform);
				//初始化相机
				this.camera = new THREE.PerspectiveCamera(
					75,
					canvas.width / canvas.height,
					0.1,
					1000);
				//初始化场景
				this.scene = new THREE.Scene();
				//初始化渲染器
				this.renderer = new THREE.WebGL1Renderer({
					canvas,
					antialias: true,
					alpha: true
				});
				this.renderer.setSize(canvas.width, canvas.height);
				this.renderer.setPixelRatio(THREE.$window.devicePixelRatio);
				// 设置相机位置
				this.camera.position.z = 5;

				// 轨道控制器
				const createOrbit = () => {
					this.controls = new OrbitControls(this.camera, canvas);
					this.controls.enableDamping = true; // 添加阻尼效果
					this.controls.dampingFactor = 0.1;
				};
				//创建光
				const creatLight = () => {
					this.light = new THREE.AmbientLight(0xffffff, 0.6);
					this.scene.add(this.light);
					// 平行光
					this.directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
					this.directionalLight.position.set(5, 10, 7.5); // 高位斜照
					this.directionalLight.castShadow = true;
					this.scene.add(this.directionalLight);
				}
				// 渲染函数
				const animate = () => {
					if (!this.disposing) {
						this.frameId = THREE.$requestAnimationFrame(animate);
					}
					this.controls.update(); // 阻尼效果需要更新
					this.renderer.render(this.scene, this.camera);
				};
				createOrbit();
				creatLight();
				this.loadHanfuModel(this.style);
				animate();
			})
		},
		onUnload() {
			this.disposing = true;
			THREE.$cancelAnimationFrame(this.frameId);
			THREE.PLATFORM.dispose();

			// 清理资源
			if (this.renderer) {
				this.renderer.dispose();
			}
			if (this.scene) {
				this.scene.clear();
			}
			if (this.controls) {
				this.controls.dispose();
			}
		},
		methods: {
			// 添加Promise执行方法
				async executeWithModelLoaded(operation) {
					if (this.isModelLoaded) {
						operation();
					} else {
						this.pendingOperations.push(operation);
						await this.modelLoadPromise;
					}
				},
				
				// 添加执行等待操作的方法
				executePendingOperations() {
					while (this.pendingOperations.length > 0) {
						const operation = this.pendingOperations.shift();
						try {
							operation();
						} catch (error) {
							console.error('执行等待操作时出错:', error);
						}
					}
					
					// 重置Promise以便下次使用
					this.modelLoadPromise = new Promise((resolve) => {
						this.resolveModelLoad = resolve;
					});
				},
			handleTouch(e) {
				this.platform?.dispatchTouchEvent(
					e); //如果 this.platform 存在，就调用它的 dispatchTouchEvent 方法并传入 e；如果 this.platform 不存在，就什么都不做，也不报错。
			},
			destroyCurrentModel() {
				if (this.hanfuModel) {
					// 递归移除模型所有子节点
					this.hanfuModel.traverse((child) => {
						if (child.isMesh) {
							// 销毁几何体和材质
							child.geometry.dispose();
							if (child.material) {
								child.material.dispose();
							}
						}
					});
					// 从场景中移除模型
					this.scene.remove(this.hanfuModel);
					this.hanfuModel = null;
				}
			},
			//导入汉服模型
			loadHanfuModel(modelUrl) {
				this.isModelLoaded = false;
				const loader = new GLTFLoader();
				loader.load(
					modelUrl,
					(gltf) => {
						this.hanfuModel = gltf.scene;
						this.hanfuModel.position.y = -1.5;
						this.hanfuModel.scale.set(0.4, 0.4, 0.4);
						if (this.style ===
							"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
						)
							this.hanfuModel.position.y = -2;
						if (this.style ===
							"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
						){
							this.hanfuModel.position.y = -1.7;
							this.hanfuModel.scale.set(0.032, 0.032, 0.032);
							this.hanfuModel.rotation.x = Math.PI / 2;
						}
							
						this.hanfuModel.traverse((child) => {
							if (child.isMesh) {
								console.log(child);
								const newMaterial = new THREE.MeshStandardMaterial({
									color: child.material.color,
									metalness: 0.2,
									roughness: 0.46,
									map: child.material.map,
									normalMap: child.material.normalMap,
									displacementMap: child.material.displacementMap,
									displacementScale: 0.1,
								});
								child.material = newMaterial;
								child.material.map = null;
							}
						});
						
						// 应用初始参数
						this.handleColor(this.color);
						this.handleColor_1(this.color_1);
						this.handleColor_2(this.color_2);
						if (this.pattern) {
							this.handlepattern(this.pattern);
						}
						if (this.design) {
							this.handledesign(this.design);
						}
						
						this.scene.add(this.hanfuModel);
						this.isModelLoaded = true; 
						
						if (this.resolveModelLoad) {
							this.resolveModelLoad();
							this.executePendingOperations();
						}
						
						console.log("ok");
					}), undefined, (e) => {
					console.log(e)
				}
				
				console.log(this.style);
			},
			updateHanFuStyle() {
				this.destroyCurrentModel();
				this.loadHanfuModel(this.style);
			},
			changeColor(name, color) {
				this.hanfuModel.traverse((child) => {
					if (child.isMesh && child.name === name) {
						child.material.color = new THREE.Color(color);
					}
				});
			},
			handleColor(col) {
				console.log(this.style);
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb"
				) {
					this.changeColor('Object_3', col);
					this.changeColor('Object_5', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/test.glb"
				) {
					console.log("yes");
					this.changeColor('sleeves', col);
					this.changeColor('Thick_2', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
				) {
					this.changeColor('物体002', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
				) {
					this.changeColor('网格_1', col);
				}
			},
			handleColor_1(col) {
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb"
				) {
					this.changeColor('Object_2', col);
					this.changeColor('Object_4', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/test.glb"
				) {
					this.changeColor('skirt', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
				) {
					this.changeColor('物体001', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
				) {
					this.changeColor('网格_2', col);
				}
			},
			handleColor_2(col) {
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb"
				) {
					this.changeColor('Object_6', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/test.glb"
				) {
					this.changeColor('Thick_1', col);
					this.changeColor('Thick_3', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
				) {
					this.changeColor('物体', col);
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
				) {
					this.changeColor('网格', col);
				}
			},
			loadTexture(figure, position) {
				const textureLoader = new TextureLoader();
				textureLoader.load(
					figure,
					(texture) => {
						this.patternTexture = texture;
						const isPowerOfTwo = (value) => {
							return (value & (value - 1)) === 0 && value !== 0;
						};
						const isPowerOfTwoTexture = isPowerOfTwo(texture.image.width) &&
							isPowerOfTwo(texture.image.height);

						if (!isPowerOfTwoTexture) {
							// 非2的幂次方纹理，使用 ClampToEdgeWrapping
							// 非2的幂次方纹理处理
							this.patternTexture.wrapS = THREE.ClampToEdgeWrapping;
							this.patternTexture.wrapT = THREE.ClampToEdgeWrapping;
							this.patternTexture.minFilter = THREE.LinearFilter;
							this.patternTexture.magFilter = THREE.LinearFilter; // 缩小纹理时使用线性过滤，更平滑

							this.patternScale = 0.1; // 0.25表示缩小4倍，可根据需求调整
						} else {
							// 2的幂次方纹理，可以使用 RepeatWrapping
							this.patternTexture.wrapS = THREE.RepeatWrapping;
							this.patternTexture.wrapT = THREE.RepeatWrapping;
							this.patternTexture.repeat.set(10, 10);
						}



						this.applyTexture(position);
						this.patternTexture.needsUpdate = true;
					},
					undefined,
					(error) => {
						console.error('图案加载失败:', error);
					}
				);
			},
			applyTexture(position) {
				this.hanfuModel.traverse((child) => {
					if (child.isMesh) {
						if (child.name === position && this.patternTexture) {
							child.material.map = this.patternTexture;

							child.material.transparent = true; // 启用透明效果
							child.material.needsUpdate = true;
						}
					}
				});
			},

			loadDesignTexture(figure, position) {
				const textureLoader = new TextureLoader();
				textureLoader.load(
					figure,
					(texture) => {
						this.designTexture = texture;
						const isPowerOfTwo = (value) => {
							return (value & (value - 1)) === 0 && value !== 0;
						};
						const isPowerOfTwoTexture = isPowerOfTwo(texture.image.width) &&
							isPowerOfTwo(texture.image.height);

						if (!isPowerOfTwoTexture) {
							// 非2的幂次方纹理，使用 ClampToEdgeWrapping
							// 非2的幂次方纹理处理
							this.designTexture.wrapS = THREE.ClampToEdgeWrapping;
							this.designTexture.wrapT = THREE.ClampToEdgeWrapping;
							this.designTexture.minFilter = THREE.LinearFilter;
							this.designTexture.magFilter = THREE.LinearFilter;
							this.patternScale = 0.5;
						} else { // 2的幂次方纹理，可以使用 RepeatWrapping
							this.designTexture.wrapS = THREE.RepeatWrapping;
							this.designTexture.wrapT = THREE.RepeatWrapping;
							this.designTexture.repeat.set(2, 2);
						}


						this.applyDesignTexture(position);
						this.designTexture.needsUpdate = true;
					},
					undefined,
					(error) => {
						console.error('图案加载失败:', error);
					}
				);
			},
			applyDesignTexture(position) {
				this.hanfuModel.traverse((child) => {
					if (child.isMesh) {
						if (child.name === position && this.designTexture) {
							child.material.map = this.designTexture;

							child.material.transparent = true; // 启用透明效果
							child.material.needsUpdate = true;
						}
					}
				});
			},

			handlepattern(pattern) {
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb"
				) {
					this.loadTexture(pattern, "Object_5");
					this.loadTexture(pattern, "Object_3");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/test.glb"
				) {
					this.loadTexture(pattern, "sleeves");
					this.loadTexture(pattern, "Thick_2");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
				) {
					this.loadTexture(pattern, "物体002");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
				) {
					this.loadTexture(pattern, "网格");
					this.loadTexture(pattern, "网格_2");
				}
			},
			handledesign(pattern) {
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb"
				) {
					this.loadDesignTexture(pattern, "Object_2");
					this.loadDesignTexture(pattern, "Object_4");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/test.glb"
				) {
					this.loadDesignTexture(pattern, "skirt");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/outside.glb?1"
				) {
					this.loadDesignTexture(pattern, "物体001");
				}
				if (this.style ===
					"https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/man.glb"
				) {
					this.loadDesignTexture(pattern, "网格_1");
				}
			}
		},
		props: {
			color: {
				type: String,
				default: '#FFFFFF' // 默认值，避免未传参时出错
			},
			color_1: {
				type: String,
				default: '#000000'
			},
			color_2: {
				type: String,
				default: '#FF0000'
			},
			style: {
				type: String,
				default: 'https://hub.gitmirror.com/https://raw.githubusercontent.com/zhang666jl/data/refs/heads/main/chest_height.glb'
			},
			pattern: {
				type: String,
				default: ''
			},
			design: {
				type: String,
				default: ''
			},
			fabric: {
				type: String,
				default: ''
			}
		},
		watch: {
			async color(col) {
				await this.executeWithModelLoaded(() => {
					this.handleColor(col);
				});
			},
			async color_1(col) {
				await this.executeWithModelLoaded(() => {
					this.handleColor_1(col);
				});
			},
			async color_2(col) {
				await this.executeWithModelLoaded(() => {
					this.handleColor_2(col);
				});
			},
			async style(sty) {
				await this.executeWithModelLoaded(() => {
					this.updateHanFuStyle();
				});
			},
			async pattern(pattern) {
				if (pattern) {
					await this.executeWithModelLoaded(() => {
						this.handlepattern(pattern);
					});
				}
			},
			async design(design) {
				if (design) {
					await this.executeWithModelLoaded(() => {
						this.handledesign(design);
					});
				}
			}
		}
	}
</script>

<style scoped>
	.container {
		width: 100%;
		height: 500rpx;
		display: flex;
		flex-direction: column;
		background-color: antiquewhite;
	}

	.webgl {
		width: 100%;
		height: 100%;
	}
</style>